✂ PostgreSQL → Git Structure

pg_atropos

Snip your dumps into manageable threads

Split PostgreSQL custom-format dumps into individual files — each table, function, index, and role in its own file. Clean diffs, clear history, no more merge conflicts.

# Split a dump into individual files

$ pg_atropos -f dump.pgdump -o ./structure

# From local database

$ pg_dump -Fc mydb | pg_atropos -f - -o ./structure

# From remote server via connection string

$ pg_dump -Fc postgresql://user@host:5432/db | pg_atropos -f - -o ./structure

✓ Extracted 24 objects to ./structure▌

What is pg_atropos?

pg_atropos is a Go command-line tool that splits PostgreSQL pg_dump -Fc (custom-format) dumps into individual files organized for Git versioning. Instead of wrestling with a single giant SQL file, each database object gets its own file — tables in TABLE/, functions in FUNCTION/, roles in ROLE/, and so on.

Rather than parsing raw SQL text with brittle regex, it pipes through pg_restore -f - which reliably emits clean -- Name: ...; Type: ... headers. The result: simpler, faster, and far more robust parsing.

Why split your dump?

✂

Minimal conflicts

Two people can change different tables without stepping on each other. No more "merge conflict in 500-line SQL file."

🔍

Clear code review

A diff shows exactly the changed object, not 500 lines of dump header. Review becomes a pleasure.

📜

Readable history

git log -- TABLE/users.sql shows every change to that specific table. Full audit trail per object.

🚀

CI/CD friendly

Deploy only the changed object, not the entire dump. Faster pipelines, less risk.

Installation

🍺

Homebrew (recommended)

The easiest way to install on macOS and Linux.

$ brew install heptau/tap/pg-atropos

⚙

From source

Requires Go 1.23+.

$ git clone https://github.com/heptau/pg_atropos.git

$ cd pg_atropos && make build

* Requires pg_restore (from PostgreSQL client tools) in your PATH.

Usage & Flags

pg_atropos works from a dump file, a live database, or stdin pipe. Here are all supported flags:

Flag Default Description
--db""Database name to dump
--conn""PostgreSQL connection string
--file, -f""Custom-format dump file ("-" for stdin)
--output, -o./outputOutput directory
--mode, -moriginOutput mode: origin | custom
--cleanfalseClean output directory before processing
--no-db-pathfalseDon't include database name in output path
--blacklist-db^(template|postgres)Skip databases matching pattern
--whitelist-db""Only include databases matching pattern
--exclude-obj""Exclude object types matching pattern
--acl-filesfalseSave ACLs to separate .acl.sql files
--move-rolesfalseMove role files under database directory
--dry-runfalsePrint what would be extracted without writing
--quietfalseSuppress informational output
--version—Print version and exit

Examples

# From a custom-format dump file

$ pg_atropos -f dump.pgdump -o ./structure

# From a live database (auto-dump via pg_dump)

$ pg_atropos -d mydb -o ./structure

# Pipe from remote database via connection string

$ pg_dump -Fc postgresql://user@host:5432/db | pg_atropos -f - -o ./structure

# Custom mode (lowercase directories for CI)

$ pg_atropos -f dump.pgdump -o ./structure -m custom

Modes

origin (default)

Mirrors the dump structure exactly — each object type gets its own directory (TABLE/, FUNCTION/, INDEX/, …). Ideal for inspection and manual browsing.

custom

Lowercase directories (table/, function/, …). Better suited for CI / automation workflows. Note: INDEX/CONSTRAINT/TRIGGER merging into table files is not supported (pg_restore headers lack parent table name).

The Name

In Greek mythology, the three Moirai (Fates) spun the thread of life, measured it, and — finally — Atropos (the Inevitable) cut it with her shears. pg_atropos does the same: it takes a giant pg_dump file and snips it into small, manageable threads (files) ready for Git.

Performance

Tested on ~150 objects / 2226 lines of SQL output:

VersionAvg Timevs pg_atropos
pg_atropos (Go)0.044s1×
pgdump_splitter (Go)0.109s2.5× slower